package com.example.appointment.service.impl;

import com.example.appointment.dto.ActivityRegistrationDTO;
import com.example.appointment.entity.ActivityRegistration;
import com.example.appointment.entity.ClubActivity;
import com.example.appointment.entity.User;
import com.example.appointment.exception.BusinessException;
import com.example.appointment.exception.ResourceNotFoundException;
import com.example.appointment.repository.ActivityRegistrationRepository;
import com.example.appointment.repository.ClubActivityRepository;
import com.example.appointment.repository.UserRepository;
import com.example.appointment.service.ActivityRegistrationService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 活动报名服务实现类
 */
@Service
public class ActivityRegistrationServiceImpl implements ActivityRegistrationService {

    @Autowired
    private ActivityRegistrationRepository registrationRepository;
    
    @Autowired
    private ClubActivityRepository activityRepository;
    
    @Autowired
    private UserRepository userRepository;

    @Override
    @Transactional
    public ActivityRegistrationDTO registerForActivity(Long activityId, Long userId) {
        // 检查活动是否存在
        ClubActivity activity = activityRepository.findById(activityId)
                .orElseThrow(() -> new ResourceNotFoundException("活动不存在"));
        
        // 检查用户是否存在
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new ResourceNotFoundException("用户不存在"));
        
        // 检查活动是否已结束
        if (activity.getEndTime().isBefore(LocalDateTime.now())) {
            throw new BusinessException("活动已结束，无法报名");
        }
        
        // 检查活动是否已达到人数上限
        if (activity.getCurrentParticipants() >= activity.getMaxParticipants()) {
            throw new BusinessException("活动报名人数已达上限");
        }
        
        // 检查用户是否已报名
        Optional<ActivityRegistration> existingRegistration = 
                registrationRepository.findByUserIdAndActivityId(userId, activityId);
        
        if (existingRegistration.isPresent()) {
            throw new BusinessException("您已报名该活动");
        }
        
        // 创建报名记录
        ActivityRegistration registration = new ActivityRegistration();
        registration.setActivity(activity);
        registration.setUser(user);
        registration.setAttended(false);
        
        // 保存报名记录
        ActivityRegistration savedRegistration = registrationRepository.save(registration);
        
        // 更新活动报名人数
        activity.setCurrentParticipants(activity.getCurrentParticipants() + 1);
        activityRepository.save(activity);
        
        // 返回DTO
        return convertToDTO(savedRegistration);
    }

    @Override
    @Transactional
    public void cancelRegistration(Long activityId, Long userId) {
        // 检查活动是否存在
        ClubActivity activity = activityRepository.findById(activityId)
                .orElseThrow(() -> new ResourceNotFoundException("活动不存在"));
        
        // 检查报名记录是否存在
        ActivityRegistration registration = registrationRepository
                .findByUserIdAndActivityId(userId, activityId)
                .orElseThrow(() -> new ResourceNotFoundException("未找到报名记录"));
        
        // 检查活动是否已开始
        if (activity.getStartTime().isBefore(LocalDateTime.now())) {
            throw new BusinessException("活动已开始，无法取消报名");
        }
        
        // 删除报名记录
        registrationRepository.delete(registration);
        
        // 更新活动报名人数
        activity.setCurrentParticipants(activity.getCurrentParticipants() - 1);
        activityRepository.save(activity);
    }

    @Override
    @Transactional
    public ActivityRegistrationDTO submitFeedback(Long activityId, Long userId, String feedback, Integer rating) {
        // 检查活动是否存在
        ClubActivity activity = activityRepository.findById(activityId)
                .orElseThrow(() -> new ResourceNotFoundException("活动不存在"));
        
        // 检查报名记录是否存在
        ActivityRegistration registration = registrationRepository
                .findByUserIdAndActivityId(userId, activityId)
                .orElseThrow(() -> new ResourceNotFoundException("您未报名该活动，无法评价"));
        
        // 检查活动是否已结束
        if (activity.getEndTime().isAfter(LocalDateTime.now())) {
            throw new BusinessException("活动尚未结束，无法评价");
        }
        
        // 检查评分范围
        if (rating != null && (rating < 1 || rating > 5)) {
            throw new BusinessException("评分必须在1-5之间");
        }
        
        // 更新评价信息
        registration.setFeedback(feedback);
        registration.setRating(rating);
        
        // 保存更新
        ActivityRegistration updatedRegistration = registrationRepository.save(registration);
        
        // 返回DTO
        return convertToDTO(updatedRegistration);
    }

    @Override
    public List<ActivityRegistrationDTO> getUserRegistrations(Long userId) {
        List<ActivityRegistration> registrations = registrationRepository.findByUserId(userId);
        
        return registrations.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    public boolean isUserRegistered(Long activityId, Long userId) {
        return registrationRepository.findByUserIdAndActivityId(userId, activityId).isPresent();
    }

    @Override
    public int getActivityRegistrationCount(Long activityId) {
        return registrationRepository.countByActivityId(activityId);
    }

    @Override
    public Page<ActivityRegistrationDTO> getActivityRegistrations(Long activityId, Pageable pageable) {
        Page<ActivityRegistration> registrationsPage = registrationRepository.findByActivityId(activityId, pageable);
        
        return registrationsPage.map(this::convertToDTO);
    }

    @Override
    public List<ActivityRegistrationDTO> getActivityFeedbacks(Long activityId) {
        List<ActivityRegistration> feedbacks = registrationRepository.findByActivityIdAndFeedbackIsNotNull(activityId);
        
        return feedbacks.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void markAttendance(Long registrationId, boolean attended) {
        ActivityRegistration registration = registrationRepository.findById(registrationId)
                .orElseThrow(() -> new ResourceNotFoundException("报名记录不存在"));
        
        registration.setAttended(attended);
        registrationRepository.save(registration);
    }
    
    /**
     * 将实体转换为DTO
     */
    private ActivityRegistrationDTO convertToDTO(ActivityRegistration registration) {
        ActivityRegistrationDTO dto = new ActivityRegistrationDTO();
        BeanUtils.copyProperties(registration, dto);
        
        // 设置活动信息
        ClubActivity activity = registration.getActivity();
        dto.setActivityId(activity.getId());
        dto.setActivityTitle(activity.getTitle());
        dto.setActivityStartTime(activity.getStartTime());
        dto.setActivityEndTime(activity.getEndTime());
        dto.setActivityLocation(activity.getLocation());
        
        // 设置用户信息
        User user = registration.getUser();
        dto.setUserId(user.getId());
        dto.setUserName(user.getName());
        
        return dto;
    }
} 